package com.DFB.common.controller;

import com.DFB.common.model.Result;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.model.COSObject;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.region.Region;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 文件上传和下载
 */
@RestController
@RequestMapping("/common")
public class CommonController {
    private static final Logger log = org.slf4j.LoggerFactory.getLogger(CommonController.class);
    private final COSClient cosClient;
    private final String bucketName;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public CommonController() {
        /* 初始化云存储客户端 */
        COSCredentials credentials = new BasicCOSCredentials("AKIDiMAqeXI1YtFl7GArKafYHm7atz7A0d4K", "95rTt7931mJen0DUaUCgx4MWUEjz3yjK");
        ClientConfig clientConfig = new ClientConfig(new Region("ap-nanjing"));
        cosClient = new COSClient(credentials, clientConfig);
        bucketName = "dfb-1317485369";
    }

    /**
     * 文件上传
     *
     * @param file
     * @return
     */
    @PostMapping("/upload")
    public Result<String> upload(MultipartFile file) {
        try {
            /* 创建上传请求 */
            String name = UUID.randomUUID() + getFileExtension(file);
            String key = "image/" + name;  // 对象键，即上传到 COS 的路径

            // 清除缓存中的对应文件
            String prefix = "image/";
            Set<String> keys = redisTemplate.keys(prefix + "*");
            if (keys != null) {
                redisTemplate.delete(keys);
            }

            InputStream inputStream = file.getInputStream(); // 获取输入流
            ObjectMetadata objectMetadata = new ObjectMetadata();

            // 设置内容长度
            objectMetadata.setContentLength(file.getSize());
            // 设置内容类型
            objectMetadata.setContentType(file.getContentType());
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, inputStream, objectMetadata);

            /* 执行上传请求 */
            PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);

            /* 返回上传后的文件路径 */
            return Result.success(name);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error();
        }
    }

    // 获取文件扩展名
    private String getFileExtension(MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        if (originalFilename != null) {
            return originalFilename.substring(originalFilename.lastIndexOf("."));
        }
        return null;
    }

    /**
     * 文件下载
     *
     * @param name
     * @param response
     */
    @GetMapping("/download")
    public void download(String name, HttpServletResponse response) {
        try {
            // 对象键，即要下载的文件路径
            String key = "image/" + name;

            // 先从缓存中获取对应的文件
            byte[] fileBytes = (byte[]) redisTemplate.opsForValue().get(key);
            if (fileBytes != null) {
                // 如果缓存中存在文件，直接返回文件
                response.setContentType("image/jpeg");
                response.setHeader("Content-Disposition", "attachment; filename=" + name);
                response.getOutputStream().write(fileBytes);
            } else {
                // 获取 COS 对象数据流
                COSObject cosObject = cosClient.getObject(bucketName, key);
                try (InputStream inputStream = cosObject.getObjectContent();
                     ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
                    // 在文件写入响应流之前, 将文件内容保存到字节数组中
                    byte[] buffer = new byte[1024];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        byteArrayOutputStream.write(buffer, 0, bytesRead);
                    }
                    // 将字节数组加入缓存
                    fileBytes = byteArrayOutputStream.toByteArray();
                    redisTemplate.opsForValue().set(key, fileBytes, 60, TimeUnit.MINUTES);

                    // 设置响应头信息
                    ObjectMetadata objectMetadata = cosClient.getObjectMetadata(bucketName, key);
                    response.setContentType(objectMetadata.getContentType());
                    response.setHeader("Content-Disposition", "attachment; filename=" + name);

                    // 将文件写入响应流
                    response.getOutputStream().write(fileBytes);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}